#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include "openssl/sha.h"
#include "cephfs/libcephfs.h"
#include "PublicFunction.h"

using namespace std;


string sha256(const string& str)
{
    char buf[5];
    unsigned char hash[SHA256_DIGEST_LENGTH];
    SHA256_CTX sha256;
    SHA256_Init(&sha256);
    SHA256_Update(&sha256, str.c_str(), str.size());
    SHA256_Final(hash, &sha256);
    std::string NewString;
    NewString.reserve(SHA256_DIGEST_LENGTH);
    for(int i = 0; i < SHA256_DIGEST_LENGTH; i++)
    {
        sprintf(buf,"%02x",hash[i]);
        NewString = NewString + buf;
    }
    return NewString;
}

std::string generateUUID() {
    boost::uuids::random_generator gen;
    boost::uuids::uuid id = gen();
    auto res = boost::uuids::to_string(id);
    boost::algorithm::replace_all(res, "-", "");
    return res;
}

void splitString(const std::string& s, std::vector<std::string>& v, const std::string& c)
{
    std::string::size_type pos1, pos2;
    pos2 = s.find(c);
    pos1 = 0;
    while(std::string::npos != pos2)
    {
        v.push_back(s.substr(pos1, pos2-pos1));

        pos1 = pos2 + c.size();
        pos2 = s.find(c, pos1);
    }
    if(pos1 != s.length())
        v.push_back(s.substr(pos1));
}

void splitString(const char* src, std::vector<std::string>& v, const char* separator=NULL)
{
    char *pNext;
//    int count = 0;
    if (src == NULL || strlen(src) == 0) //如果传入的地址为空或长度为0，直接终止
        return;
    if (separator == NULL || strlen(separator) == 0) {//如未指定分割的字符串，直接终止}
        pNext = const_cast<char *>(src);
        while((*pNext) != '\0') {
            v.emplace_back(1,*pNext);
            pNext++;
        }

    } else {
        char* pSrc = const_cast<char *>(src);
        pNext = strsep(&pSrc, separator);
//        pNext = (char *)strtok(const_cast<char *>(src),separator); //必须使用(char *)进行强制类型转换(虽然不写有的编译器中不会出现指针错误)
        while(pNext != NULL) {
            v.emplace_back(pNext);
            pNext = strsep(&pSrc, separator);
//            pNext = (char *)strtok(nullptr,separator);  //必须使用(char *)进行强制类型转换
        }
    }
}


int GetFileNames(const string& path,vector<string>& filenames)
{
    DIR *pDir;
    struct dirent* ptr;
    if(!(pDir = opendir(path.c_str()))){
        cout<<"Folder doesn't Exist!"<<endl;
        return -1;
    }
    while((ptr = readdir(pDir))!=0) {
        if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0 && ptr->d_type == DT_REG){
            filenames.push_back(ptr->d_name);
        }
    }
    closedir(pDir);
    return 0;
}

int GetSubFolders(const string& path,vector<string>& foldernames)
{
    DIR *pDir;
    struct dirent* ptr;
    if(!(pDir = opendir(path.c_str()))){
        cout<<"Folder doesn't Exist!"<<endl;
        return -1;
    }
    while((ptr = readdir(pDir))!=0) {
        if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0 && ptr->d_type == DT_DIR){
            foldernames.push_back(ptr->d_name);
        }
    }
    closedir(pDir);
    return 0;
}

int readFile(const std::string& path, std::string& content) {
    int fd = open(path.c_str(), O_RDONLY, S_IRUSR);
    if ( fd < 0 )
        return fd;
    //flock(fd, LOCK_EX);

    flock(fd, LOCK_SH);
    //cout<<"lock success"<<endl;
    struct stat st;
    int fs = fstat(fd, &st);
    if ( fs < 0 )
    {
        close(fd);
        return fs;
    }
    char *buf = new char[st.st_size];
    ssize_t rs = read(fd, buf, st.st_size);
    if ( rs < 0 )
    {
        close(fd);
        return rs;
    }
    content.assign(buf, rs);
    if ( buf )
        delete buf;
    //flock(fd, LOCK_UN);
    close(fd);
    return 0;
    //    std::ifstream ifile;
    //    ifile.open(path, std::ios::in|std::ios::binary);
    //    if (!ifile ) {
    //        return -1;
    //    }
    //    std::stringstream ss;
    //    ss << ifile.rdbuf();
    //    content = ss.str();
    //    ifile.close();
    //    return 0;
}

int writeFile(const std::string& path, const std::string& content) {
    int fd = open(path.c_str(), O_WRONLY|O_TRUNC|O_CREAT, S_IRUSR);
    if ( fd < 0 )
        return fd;
    flock(fd, LOCK_EX);

    int ws = write(fd, content.data(), content.size());
    close(fd);
    return ws;

    //    std::ofstream ofile;
    //    ofile.open(path, ios_base::out | ios_base::trunc);
    //    if (!ofile) {
    //        return -1;
    //    }
    //    ofile << content;
    //    ofile.close();
    //    return 0;
}

